001    /*
002     * Copyright 2005 Stephen J. McConnell
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.tools.tasks;
020    
021    import java.io.File;
022    import java.io.OutputStream;
023    import java.io.FileOutputStream;
024    import java.io.OutputStreamWriter;
025    import java.io.Writer;
026    import java.net.URI;
027    
028    import net.dpml.lang.Version;
029    
030    import net.dpml.library.Module;
031    import net.dpml.library.Resource;
032    import net.dpml.library.Type;
033    
034    import net.dpml.transit.Artifact;
035    import net.dpml.transit.link.ArtifactLinkManager;
036    
037    import org.apache.tools.ant.BuildException;
038    import org.apache.tools.ant.Project;
039    import org.apache.tools.ant.types.FileSet;
040    import org.apache.tools.ant.taskdefs.Copy;
041    
042    /**
043     * Execute the install phase.
044     *
045     * @author <a href="http://www.dpml.net">The Digital Product Meta Library</a>
046     * @version 1.0.0
047     */
048    public class InstallTask extends GenericTask
049    {    
050       /**
051        * Execute the project.
052        * @exception BuildException if a build errror occurs
053        */
054        public void execute() throws BuildException
055        {
056            installDeliverables();
057        }
058    
059        private void installDeliverables()
060        {
061            Resource resource = getResource();
062            Type[] types = resource.getTypes();
063            if( types.length == 0 )
064            {
065                return;
066            }
067            
068            final File deliverables = getContext().getTargetDeliverablesDirectory();
069            for( int i=0; i < types.length; i++ )
070            {
071                Type type = types[i];
072                
073                //
074                // Check that the project has actually built the resource
075                // type that it declares
076                //
077    
078                String id = type.getID();
079                String filename = getContext().getLayoutFilename( id );
080                File group = new File( deliverables, id + "s" );
081                File target = new File( group, filename );
082                if( !target.exists() && !id.equalsIgnoreCase( "null" ) )
083                {
084                    final String error = 
085                      "Project [" 
086                      + resource 
087                      + "] declares that it produces the resource type ["
088                      + id
089                      + "] however no artifacts of that type are present in the target deliverables directory.";
090                    throw new BuildException( error, getLocation() );
091                }
092    
093                //
094                // If the type declares an alias then construct a link 
095                // and add the link to the deliverables directory as part of 
096                // install process.
097                //
098    
099                Version version = type.getVersion();
100                if( null != version )
101                {
102                    try
103                    {
104                        Artifact artifact = resource.getArtifact( id );
105                        String uri = artifact.toURI().toASCIIString();
106                        
107                        String link = null;
108                        if( Version.NULL_VERSION.equals( version ) )
109                        {
110                            link = resource.getName() + "." + id + ".link";
111                        }
112                        else
113                        {
114                            link = resource.getName()
115                            + "-"
116                            + version.getMajor()
117                            + "." 
118                            + version.getMinor()
119                            + "."
120                            + id + ".link";
121                        }
122                        File out = new File( group, link );
123                        boolean flag = true;
124                        if( out.exists() )
125                        {
126                            ArtifactLinkManager manager = new ArtifactLinkManager();
127                            URI enclosed = manager.getTargetURI( new URI( out.toURL().toString() ) );
128                            if( artifact.toURI().equals( enclosed ) )
129                            {
130                                flag = false;
131                            }
132                        }
133                        
134                        if( flag )
135                        {
136                            log( link.toString() );
137                            log( uri.toString() );
138                            out.createNewFile();
139                            final OutputStream output = new FileOutputStream( out );
140                            final Writer writer = new OutputStreamWriter( output );
141                            writer.write( uri );
142                            writer.close();
143                            output.close();
144                        }
145                    }
146                    catch( Exception e )
147                    {
148                        final String error = 
149                          "Internal error while attempting to create a link for the resource type ["
150                          + id 
151                          + "] in project ["
152                          + resource
153                          + "].";
154                        throw new BuildException( error, e, getLocation() );
155                    }
156                }
157            }
158    
159            if( deliverables.exists() )
160            {
161                log( "Installing deliverables from [" + deliverables + "]", Project.MSG_VERBOSE );
162                final File cache = (File) getProject().getReference( "dpml.cache" );
163                log( "To cache dir [" + cache + "]", Project.MSG_VERBOSE );
164                try
165                {
166                    final FileSet fileset = new FileSet();
167                    fileset.setProject( getProject() );
168                    fileset.setDir( deliverables );
169                    fileset.createInclude().setName( "**/*" );
170                    Module parent = resource.getParent();
171                    if( null == parent )
172                    {
173                        copy( cache, fileset, true );
174                    }
175                    else
176                    {
177                        final String group = parent.getResourcePath();
178                        final File destination = new File( cache, group );
179                        copy( destination, fileset, true );
180                    }
181                }
182                catch( Throwable e )
183                {
184                    final String error = 
185                      "Unexpected error while constructing ant fileset."
186                      + "\nDeliverables dir: " + deliverables;
187                    throw new BuildException( error, e );
188                }
189            }
190        }
191        
192       /**
193        * Utility operation to copy a fileset to a destination directory.
194        * @param destination the destination directory
195        * @param fileset the fileset to copy
196        * @param preserve the preserve timestamp flag
197        */
198        public void copy( final File destination, final FileSet fileset, boolean preserve )
199        {
200            mkDir( destination );
201            final Copy copy = (Copy) getProject().createTask( "copy" );
202            copy.setTaskName( getTaskName() );
203            copy.setPreserveLastModified( preserve );
204            copy.setTodir( destination );
205            copy.addFileset( fileset );
206            copy.setOverwrite( true ); // required for filtered deliverables
207            copy.init();
208            copy.execute();
209        }
210    }